home *** CD-ROM | disk | FTP | other *** search
- unit MAKEMIC;
-
- { This unit defines the MakeMethodInstance,MakeMethodInstance32Reg and }
- { FreeMethodInstance functions. $IFDEFs are used to tailor the unit to the }
- { different versions of Delphi. }
-
- interface
-
- uses WinTypes, WinProcs, SysUtils;
-
- procedure FreeMethodInstance(Instance: Pointer);
- function MakeMethodInstance(Code,Data: Pointer): Pointer;
- {$IFDEF WIN32}
- function MakeMethodInstance32Reg(Code,Data: Pointer; OptCount: Integer): Pointer;
- {$ENDIF}
-
- implementation
-
- type
- PJumpBlock = ^TJumpBlock;
- TJumpBlock = packed record
- {$IFDEF WIN32}
- POP_EAX_OpCode: Byte;
- Push_Immed_OpCode: Byte;
- Self_Value: Pointer;
- PUSH_EAX_OpCode: Byte;
- Jmp_OpCode: Byte;
- Method_Addr: Pointer;
- DummyAddr: Byte;
- {$ELSE}
- POP_AX_OpCode: Byte;
- POP_CX_OpCode: Byte;
- Push_Seg_Immed_OpCode: Byte;
- Self_Seg_Value: Word;
- Push_Ofs_Immed_OpCode: Byte;
- Self_Ofs_Value: Word;
- PUSH_CX_OpCode: Byte;
- PUSH_AX_OpCode: Byte;
- Jmp_OpCode: Byte;
- Method_Addr: Pointer;
- { Specific information needed for 16 bit segmented memory }
- DataSelector: THandle;
- CodeSelector: THandle;
- {$ENDIF}
- end;
-
- function MakeMethodInstance(Code,Data: Pointer): Pointer;
- {$IFNDEF WIN32}
- var
- WrkHData,WrkHCode: THandle;
- {$ENDIF}
-
- begin
- {$IFDEF WIN32}
- Result := VirtualAlloc(nil,sizeof(TJumpBlock),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
- if Result <> nil then
- With PJumpBlock(Result)^ do
- begin
- POP_EAX_OpCode := $58; { POP Return address into EAX register }
- Push_Immed_OpCode := $68; { PUSH DWORD following this instruction }
- Self_Value := Data; { Set DWORD to the object instance address }
- PUSH_EAX_OpCode := $50; { Push the return address back on the stack }
- Jmp_OpCode := $E9; { JMP to the relative offset following this opcode }
- Method_Addr := Pointer(LongInt(Code) - LongInt(@DummyAddr));
- end;
- {$ELSE}
- WrkHData := GlobalAlloc(HeapAllocFlags,SizeOf(TJumpBlock));
- Result := GlobalLock(WrkHData);
- if Result <> nil then
- With PJumpBlock(Result)^ do
- begin
- POP_AX_OpCode := $58; { POP Return address into EAX register }
- POP_CX_OpCode := $59; { POP Return address into ECX register }
- Push_Seg_Immed_OpCode := $68; { PUSH the Self segment value onto stack }
- Self_Seg_Value := PtrRec(Data).Seg;
- Push_Ofs_Immed_OpCode := $68; { PUSH the Self segment offset onto stack }
- Self_Ofs_Value := PtrRec(Data).Ofs;
- PUSH_CX_OpCode := $51; { PUSH the CX register back onto the stack }
- PUSH_AX_OpCode := $50; { PUSH the AX register back onto the stack }
- Jmp_OpCode := $EA; { JMP to the address following this opcode }
- Method_Addr := Code;
- WrkHCode := AllocDsToCSAlias(PtrRec(Result).Seg);
- PtrRec(Result).Seg := WrkHCode;
- { Store the code and data selectors for FreeMethodInstance }
- DataSelector := WrkHData;
- CodeSelector := WrkHCode;
- end;
- {$ENDIF}
- end;
-
- procedure FreeMethodInstance(Instance: Pointer);
- {$IFNDEF WIN32}
- var
- WrkHData,WrkHCode: THandle;
- {$ENDIF}
-
- begin
- {$IFDEF WIN32}
- if Instance <> nil then
- VirtualFree(Instance,0,MEM_DECOMMIT);
- {$ELSE}
- if Instance <> nil then
- With PJumpBlock(Instance)^ do
- begin
- WrkHData := DataSelector;
- WrkHCode := CodeSelector;
- GlobalUnlock(WrkHData);
- GlobalFree(WrkHData);
- FreeSelector(WrkHCode);
- end;
- {$ENDIF}
- end;
-
- {==============================================================================}
- { All code following this comment is only available in Delphi 2 }
- {==============================================================================}
-
- {$IFDEF WIN32}
- type
- PJumpBlockOpt0 = ^TJumpBlockOpt0;
- TJumpBlockOpt0 = packed record
- MOV_EAX_Immed_OpCode: Byte;
- Self_Value: Pointer;
- Jmp_OpCode: Byte;
- Method_Addr: Pointer;
- DummyAddr: Byte;
- end;
-
- type
- PJumpBlockOpt1 = ^TJumpBlockOpt1;
- TJumpBlockOpt1 = packed record
- MOV_EAX_2_EDX_OpCode: Word;
- MOV_EAX_Immed_OpCode: Byte;
- Self_Value: Pointer;
- Jmp_OpCode: Byte;
- Method_Addr: Pointer;
- DummyAddr: Byte;
- end;
-
- type
- PJumpBlockOpt2 = ^TJumpBlockOpt2;
- TJumpBlockOpt2 = packed record
- MOV_EDX_2_ECX_OpCode: Word;
- MOV_EAX_2_EDX_OpCode: Word;
- MOV_EAX_Immed_OpCode: Byte;
- Self_Value: Pointer;
- Jmp_OpCode: Byte;
- Method_Addr: Pointer;
- DummyAddr: Byte;
- end;
-
- type
- PJumpBlockOpt3 = ^TJumpBlockOpt3;
- TJumpBlockOpt3 = packed record
- MOV_ECX_2_ParmStore_OpCode: Word;
- Parm3_Store_Address: Pointer;
- POP_ECX_OpCode: Byte;
- MOV_ECX_2_RetAddrStore_OpCode: Word;
- RetAddr_Store_Address: Pointer;
- MOV_EDX_2_ECX_OpCode: Word;
- MOV_EAX_2_EDX_OpCode: Word;
- MOV_ParmStore_2_EAX_OpCode: Byte;
- Parm3_Store_Address2: Pointer;
- PUSH_Parm3_From_EAX_OpCode: Byte;
- MOV_RetAddr_2_EAX_OpCode: Byte;
- RetAddr_Store_Address2: Pointer;
- PUSH_RetAddr_From_EAX_OpCode: Byte;
- MOV_EAX_Immed_OpCode: Byte;
- Self_Value: Pointer;
- Jmp_OpCode: Byte;
- Method_Addr: Pointer;
- DummyAddr: Byte;
- { Temp storage areas for 3rd parameter and return address }
- Temp_Parm3_Store: Pointer;
- Temp_ReturnAddr_Store: Pointer;
- end;
-
- function MakeMethodInstance32Reg(Code,Data: Pointer; OptCount: Integer): Pointer;
- begin
- Result := nil;
- if OptCount in [0..3] then
- begin
- Result := VirtualAlloc(nil,sizeof(TJumpBlockOpt3),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
- if Result <> nil then
- case OptCount of
- 0:
-
- With PJumpBlockOpt0(Result)^ do
- begin
- MOV_EAX_Immed_OpCode := $B8; { Move DWORD following this instruction into EAX register }
- Self_Value := Data; { Set DWORD to the object instance address }
- Jmp_OpCode := $E9; { JMP to the relative offset following this opcode }
- Method_Addr := Pointer(LongInt(Code) - LongInt(@DummyAddr));
- end;
-
- 1:
-
- With PJumpBlockOpt1(Result)^ do
- begin
- MOV_EAX_2_EDX_OpCode := $D08B; { Copy EAX register to the EDX register }
- MOV_EAX_Immed_OpCode := $B8; { Move DWORD following this instruction into EAX register }
- Self_Value := Data; { Set DWORD to the object instance address }
- Jmp_OpCode := $E9; { JMP to the relative offset following this opcode }
- Method_Addr := Pointer(LongInt(Code) - LongInt(@DummyAddr));
- end;
-
- 2:
-
- With PJumpBlockOpt2(Result)^ do
- begin
- MOV_EDX_2_ECX_OpCode := $CA8B; { Copy EDX register to ECX register }
- MOV_EAX_2_EDX_OpCode := $D08B; { Copy EAX register to the EDX register }
- MOV_EAX_Immed_OpCode := $B8; { Move DWORD following this instruction into EAX register }
- Self_Value := Data; { Set DWORD to the object instance address }
- Jmp_OpCode := $E9; { JMP to the relative offset following this opcode }
- Method_Addr := Pointer(LongInt(Code) - LongInt(@DummyAddr));
- end;
-
- 3:
-
- With PJumpBlockOpt3(Result)^ do
- begin
- MOV_ECX_2_ParmStore_OpCode := $0D89;
- Parm3_Store_Address := @Temp_Parm3_Store;
- POP_ECX_OpCode := $59;
- MOV_ECX_2_RetAddrStore_OpCode := $0D89;
- RetAddr_Store_Address := @Temp_ReturnAddr_Store;
- MOV_EDX_2_ECX_OpCode := $CA8B;
- MOV_EAX_2_EDX_OpCode := $D08B;
- MOV_ParmStore_2_EAX_OpCode := $A1;
- Parm3_Store_Address2 := @Temp_Parm3_Store;
- PUSH_Parm3_From_EAX_OpCode := $50;
- MOV_RetAddr_2_EAX_OpCode := $A1;
- RetAddr_Store_Address2 := @Temp_ReturnAddr_Store;
- PUSH_RetAddr_From_EAX_OpCode := $50;
- MOV_EAX_Immed_OpCode := $B8; { Move DWORD following this instruction into EAX register }
- Self_Value := Data; { Set DWORD to the object instance address }
- Jmp_OpCode := $E9; { JMP to the relative offset following this opcode }
- Method_Addr := Pointer(LongInt(Code) - LongInt(@DummyAddr));
- end;
- end;
- end;
- end;
-
- {$ENDIF}
-
- end.
-